package core

import(
	"fmt"
	"sync"
)
type Grid struct{
	GID       int          //格子ID
	MinX      int          //格子左边界坐标
	MaxX      int          //格子右边界坐标
	MinY      int          //格子上边界坐标
	MaxY      int          //格子下边界坐标
	playerIDs map[int]bool //当前格子内的玩家或者物体成员ID (在就是true，不在就是false)
	pIDLock   sync.RWMutex   //playerIDs的保护map的锁
}
var playerIDs []int
//初始化一个格子
func NewGrid(gID, minX, maxX, minY, maxY int) *Grid {
	return &Grid{
		GID:gID,
		MinX:minX,
		MaxX:maxX,
		MinY:minY,
		MaxY:maxY,
		playerIDs:make(map[int] bool),
	}
}

//向当前格子中添加一个玩家
func (g *Grid) Add(playerID int) {
	g.pIDLock.Lock()
	defer g.pIDLock.Unlock()

	g.playerIDs[playerID] = true
}

//从格子中删除一个玩家
func (g *Grid) Remove(playerID int) {
	g.pIDLock.Lock()
	defer g.pIDLock.Unlock()

	delete(g.playerIDs, playerID)
}

//得到当前格子中所有的玩家
func (g *Grid) GetPlyerIDs() (playerIDs []int) {//返回一个切片类型即可
	g.pIDLock.RLock()
	defer g.pIDLock.RUnlock()
// playerIDs是作为局部变量的，所以就是[]，作为返回值的是后已经被声明了！！！
	for k, _ := range g.playerIDs {
		playerIDs = append(playerIDs, k)    
	}

	return
}
/*Grid这个格子类型，很好理解，分别有上下左右四个坐标，确定格子的领域范围，还是有格子ID，
其中playerIDs是一个map，表示当前格子中存在的玩家有哪些。
这里提供了一个方法GetPlyerIDs()可以返回当前格子中所有玩家的ID切片。
*/


//打印信息方法
func (g *Grid) String() string {              //重写String方法
	return fmt.Sprintf("Grid id: %d, minX:%d, maxX:%d, minY:%d, maxY:%d, playerIDs:%v",
		g.GID, g.MinX, g.MaxX, g.MinY, g.MaxY, g.playerIDs)
}
// 在go中如果重写了String 方法，那在调用fmt.Println时就会自动去执行String 方法
/*
 Printf()、Sprintf()、Fprintf() 函数的区别用法是什么？

　　都是输出格式化字符串，只是输出到的目标不一样：

　　　　Printf() 是把格式化字符串输出到标准到标准输出（一般是屏幕，可以重定向）

　　　　Printf() 是和标准输出文件（stdout）关联的，Fprintf 则没有这个限制

　　　　Sprintf() 是把格式化字符串输出到指定的字符串中，可以用一个变量来接受，然后在打印

　　　　Fprintf() 是把格式字符串输出到指定的文件设备中，所以参数比Printf 多一个文件指针*File

主要用于文件操作，Fprintf() 是格式化输出到一个 Stream ,通常是一个文件
*/